package main

import (
	"fmt"
	"log"
	"math/rand"

	"github.com/gomodule/redigo/redis"
)

func main() {
	RedisPool := &redis.Pool{
		MaxIdle:   10,
		MaxActive: 100,
		Dial: func() (redis.Conn, error) {
			conn, err := redis.Dial("tcp", "127.0.0.1:6379")
			if err != nil {
				return nil, err
			}
			return conn, nil
		},
	}

	// string
	strKey, strVal := "string_key", "string_val"
	con := RedisPool.Get()
	defer con.Close()

	if _, err := con.Do("SET", strKey, strVal); err != nil {
		log.Fatalln(err)
	}
	strVal, err := redis.String(con.Do("GET", strKey))
	if err != nil {
		log.Fatalln(err)
	}
	fmt.Println(strVal)

	// sorted_set
	strSetKey := "zset_rank"
	for i := 0; i < 10; i++ {
		if _, err := con.Do("ZADD", strSetKey, rand.Intn(1000), i); err != nil {
			log.Fatalln(err)
		}
	}
	var stMembers map[string]int
	stMembers, err = redis.IntMap(con.Do("ZREVRANGE", strSetKey, 0, 7, "WITHSCORES"))
	if err != nil {
		log.Fatalln(err)
	}
	for key, val := range stMembers {
		fmt.Println(key, val)
	}

	// hash
	type User struct {
		Name string `json:"name" redis:"name"`
		Age  int    `json:"age" redis:"age"`
	}
	user := &User{Name: "Astone", Age: 18}
	if _, err := con.Do("HMSET", redis.Args{}.Add("hash_user").AddFlat(user)...); err != nil {
		log.Fatalln(err)
	}
	user.Name, user.Age = "", 0
	if val, err := redis.Values(con.Do("HGETALL", "hash_user")); err == nil {
		if err := redis.ScanStruct(val, user); err != nil {
			log.Fatalln(err)
		}
		fmt.Println(*user)
	}

	{
		val, err := redis.String(con.Do("HGET", "hash_user", "invalid"))
		fmt.Println("err:", err)
		fmt.Println("val:", val)
	}

	// multi close is safe
	con.Close()
	con.Close()
	con.Close()

	// MGET MSET
	{
		con := RedisPool.Get()
		defer con.Close()

		_, err := con.Do("MSET", "tmp_k1", "v1", "tmp_k2", "v2")
		if err != nil {
			panic(err)
		}

		//val, err := redis.Strings(con.Do("MGET", "tmp_k1 tmp_k2 tmp_k3")) // ERROR
		val, err := redis.Strings(con.Do("MGET", "tmp_k1", "tmp_k2", "tmp_k3"))
		if err != nil {
			panic(err)
		}
		fmt.Println("val:")
		for _, v := range val {
			fmt.Printf("%v\n", v)
		}
	}
}
